package edu.hawaii.stack.configuration;

import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import edu.hawaii.stack.configuration.jaxb.Stack;
import edu.hawaii.stack.configuration.jaxb.StackElement;

/**
 * Provides access to the contents of the "default" stack.
 * The default stack is stored in ~/.stack/stack.xml
 * @author Philip Johnson
 */
public class ConfigurationManager {
  /** The JAXB Stack instance read in from the XML file. */
  private Stack stack;

  /**
   * Creates a new ConfigurationManager that reads in the XML stack representation.
   * @param configFile An XML file containing a stack representation.
   * @param schemaFile An XML file containing a stack schema representation.
   */
  public ConfigurationManager(File configFile, File schemaFile) {
    try {
      JAXBContext jaxbContext = 
        JAXBContext.newInstance(edu.hawaii.stack.configuration.jaxb.ObjectFactory.class);
      if (configFile.exists()) {
        // Left in for teaching purposes. Don't use System.out.println in production code!
        System.out.println("Loading configuration from " + configFile.getPath()); 
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        SchemaFactory schemaFactory = 
          SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = schemaFactory.newSchema(schemaFile);
        unmarshaller.setSchema(schema);
        this.stack = (Stack) unmarshaller.unmarshal(configFile);
      }
    }
    catch (Exception e) {
      throw new RuntimeException("Error in Stack ConfigurationManager", e);
    }
  }
  
  /**
   * Create a new ConfigurationManager that provides access to the stack in ~/.stack/stack.xml.
   */
  public ConfigurationManager() {
    this(new File(System.getProperty("user.home") + "/.stack/stack.xml"),
        new File(System.getProperty("user.home") + "/.stack/stack.xsd"));
  }
  
  /**
   * Returns a Stack constructed from the default XML stack. 
   * If no default Stack exists, an empty stack is returned. 
   * @return The Stack instance constructed from the XML stack. 
   */
  public edu.hawaii.stack.Stack getStack() {
    // Must fully qualify to distinguish from the JAXB version of Stack. 
    edu.hawaii.stack.Stack newStack = new edu.hawaii.stack.Stack();
    if (this.stack != null) {
      for (StackElement stackElement : this.stack.getStackElement()) {
        newStack.push(stackElement.getValue());
      }
    }
    return newStack;
  }
}
